/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package dao;

import dao.exceptions.IllegalOrphanException;
import dao.exceptions.NonexistentEntityException;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import pojo.Category;
import pojo.Sizes;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.TypedQuery;
import pojo.Colors;
import pojo.Images;
import pojo.Cart;
import pojo.Product;

/**
 *
 * @author khalifaabdelaziz
 */
public class ProductJpaController implements Serializable {

    public ProductJpaController(EntityManagerFactory emf) {
        this.emf = emf;
    }
    private EntityManagerFactory emf = null;

    public EntityManager getEntityManager() {
        return emf.createEntityManager();
    }

    public Integer create(Product product) {
        if (product.getSizesList() == null) {
            product.setSizesList(new ArrayList<Sizes>());
        }
        if (product.getColorsList() == null) {
            product.setColorsList(new ArrayList<Colors>());
        }
        if (product.getImagesList() == null) {
            product.setImagesList(new ArrayList<Images>());
        }
        if (product.getCartList() == null) {
            product.setCartList(new ArrayList<Cart>());
        }
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Category categoryId = product.getCategoryId();
            if (categoryId != null) {
                categoryId = em.getReference(categoryId.getClass(), categoryId.getId());
                product.setCategoryId(categoryId);
            }
            List<Sizes> attachedSizesList = new ArrayList<Sizes>();
            for (Sizes sizesListSizesToAttach : product.getSizesList()) {
                sizesListSizesToAttach = em.getReference(sizesListSizesToAttach.getClass(), sizesListSizesToAttach.getId());
                attachedSizesList.add(sizesListSizesToAttach);
            }
            product.setSizesList(attachedSizesList);
            List<Colors> attachedColorsList = new ArrayList<Colors>();
            for (Colors colorsListColorsToAttach : product.getColorsList()) {
                colorsListColorsToAttach = em.getReference(colorsListColorsToAttach.getClass(), colorsListColorsToAttach.getId());
                attachedColorsList.add(colorsListColorsToAttach);
            }
            product.setColorsList(attachedColorsList);
            List<Images> attachedImagesList = new ArrayList<Images>();
            for (Images imagesListImagesToAttach : product.getImagesList()) {
                imagesListImagesToAttach = em.getReference(imagesListImagesToAttach.getClass(), imagesListImagesToAttach.getId());
                attachedImagesList.add(imagesListImagesToAttach);
            }
            product.setImagesList(attachedImagesList);
            List<Cart> attachedCartList = new ArrayList<Cart>();
            for (Cart cartListCartToAttach : product.getCartList()) {
                cartListCartToAttach = em.getReference(cartListCartToAttach.getClass(), cartListCartToAttach.getCartPK());
                attachedCartList.add(cartListCartToAttach);
            }
            product.setCartList(attachedCartList);
            em.persist(product);
            if (categoryId != null) {
                categoryId.getProductList().add(product);
                categoryId = em.merge(categoryId);
            }
            for (Sizes sizesListSizes : product.getSizesList()) {
                Product oldProductIdOfSizesListSizes = sizesListSizes.getProductId();
                sizesListSizes.setProductId(product);
                sizesListSizes = em.merge(sizesListSizes);
                if (oldProductIdOfSizesListSizes != null) {
                    oldProductIdOfSizesListSizes.getSizesList().remove(sizesListSizes);
                    oldProductIdOfSizesListSizes = em.merge(oldProductIdOfSizesListSizes);
                }
            }
            for (Colors colorsListColors : product.getColorsList()) {
                Product oldProductIdOfColorsListColors = colorsListColors.getProductId();
                colorsListColors.setProductId(product);
                colorsListColors = em.merge(colorsListColors);
                if (oldProductIdOfColorsListColors != null) {
                    oldProductIdOfColorsListColors.getColorsList().remove(colorsListColors);
                    oldProductIdOfColorsListColors = em.merge(oldProductIdOfColorsListColors);
                }
            }
            for (Images imagesListImages : product.getImagesList()) {
                Product oldProductIdOfImagesListImages = imagesListImages.getProductId();
                imagesListImages.setProductId(product);
                imagesListImages = em.merge(imagesListImages);
                if (oldProductIdOfImagesListImages != null) {
                    oldProductIdOfImagesListImages.getImagesList().remove(imagesListImages);
                    oldProductIdOfImagesListImages = em.merge(oldProductIdOfImagesListImages);
                }
            }
            for (Cart cartListCart : product.getCartList()) {
                Product oldProductOfCartListCart = cartListCart.getProduct();
                cartListCart.setProduct(product);
                cartListCart = em.merge(cartListCart);
                if (oldProductOfCartListCart != null) {
                    oldProductOfCartListCart.getCartList().remove(cartListCart);
                    oldProductOfCartListCart = em.merge(oldProductOfCartListCart);
                }
            }
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }

        return product.getId();
    }

    public void edit(Product product) throws IllegalOrphanException, NonexistentEntityException, Exception {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Product persistentProduct = em.find(Product.class, product.getId());
            Category categoryIdOld = persistentProduct.getCategoryId();
            Category categoryIdNew = product.getCategoryId();
            List<Sizes> sizesListOld = persistentProduct.getSizesList();
            List<Sizes> sizesListNew = product.getSizesList();
            List<Colors> colorsListOld = persistentProduct.getColorsList();
            List<Colors> colorsListNew = product.getColorsList();
            List<Images> imagesListOld = persistentProduct.getImagesList();
            List<Images> imagesListNew = product.getImagesList();
            List<Cart> cartListOld = persistentProduct.getCartList();
            List<Cart> cartListNew = product.getCartList();
            List<String> illegalOrphanMessages = null;
            for (Sizes sizesListOldSizes : sizesListOld) {
                if (!sizesListNew.contains(sizesListOldSizes)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Sizes " + sizesListOldSizes + " since its productId field is not nullable.");
                }
            }
            for (Colors colorsListOldColors : colorsListOld) {
                if (!colorsListNew.contains(colorsListOldColors)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Colors " + colorsListOldColors + " since its productId field is not nullable.");
                }
            }
            for (Images imagesListOldImages : imagesListOld) {
                if (!imagesListNew.contains(imagesListOldImages)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Images " + imagesListOldImages + " since its productId field is not nullable.");
                }
            }
            for (Cart cartListOldCart : cartListOld) {
                if (!cartListNew.contains(cartListOldCart)) {
                    if (illegalOrphanMessages == null) {
                        illegalOrphanMessages = new ArrayList<String>();
                    }
                    illegalOrphanMessages.add("You must retain Cart " + cartListOldCart + " since its product field is not nullable.");
                }
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            if (categoryIdNew != null) {
                categoryIdNew = em.getReference(categoryIdNew.getClass(), categoryIdNew.getId());
                product.setCategoryId(categoryIdNew);
            }
            List<Sizes> attachedSizesListNew = new ArrayList<Sizes>();
            for (Sizes sizesListNewSizesToAttach : sizesListNew) {
                sizesListNewSizesToAttach = em.getReference(sizesListNewSizesToAttach.getClass(), sizesListNewSizesToAttach.getId());
                attachedSizesListNew.add(sizesListNewSizesToAttach);
            }
            sizesListNew = attachedSizesListNew;
            product.setSizesList(sizesListNew);
            List<Colors> attachedColorsListNew = new ArrayList<Colors>();
            for (Colors colorsListNewColorsToAttach : colorsListNew) {
                colorsListNewColorsToAttach = em.getReference(colorsListNewColorsToAttach.getClass(), colorsListNewColorsToAttach.getId());
                attachedColorsListNew.add(colorsListNewColorsToAttach);
            }
            colorsListNew = attachedColorsListNew;
            product.setColorsList(colorsListNew);
            List<Images> attachedImagesListNew = new ArrayList<Images>();
            for (Images imagesListNewImagesToAttach : imagesListNew) {
                imagesListNewImagesToAttach = em.getReference(imagesListNewImagesToAttach.getClass(), imagesListNewImagesToAttach.getId());
                attachedImagesListNew.add(imagesListNewImagesToAttach);
            }
            imagesListNew = attachedImagesListNew;
            product.setImagesList(imagesListNew);
            List<Cart> attachedCartListNew = new ArrayList<Cart>();
            for (Cart cartListNewCartToAttach : cartListNew) {
                cartListNewCartToAttach = em.getReference(cartListNewCartToAttach.getClass(), cartListNewCartToAttach.getCartPK());
                attachedCartListNew.add(cartListNewCartToAttach);
            }
            cartListNew = attachedCartListNew;
            product.setCartList(cartListNew);
            product = em.merge(product);
            if (categoryIdOld != null && !categoryIdOld.equals(categoryIdNew)) {
                categoryIdOld.getProductList().remove(product);
                categoryIdOld = em.merge(categoryIdOld);
            }
            if (categoryIdNew != null && !categoryIdNew.equals(categoryIdOld)) {
                categoryIdNew.getProductList().add(product);
                categoryIdNew = em.merge(categoryIdNew);
            }
            for (Sizes sizesListNewSizes : sizesListNew) {
                if (!sizesListOld.contains(sizesListNewSizes)) {
                    Product oldProductIdOfSizesListNewSizes = sizesListNewSizes.getProductId();
                    sizesListNewSizes.setProductId(product);
                    sizesListNewSizes = em.merge(sizesListNewSizes);
                    if (oldProductIdOfSizesListNewSizes != null && !oldProductIdOfSizesListNewSizes.equals(product)) {
                        oldProductIdOfSizesListNewSizes.getSizesList().remove(sizesListNewSizes);
                        oldProductIdOfSizesListNewSizes = em.merge(oldProductIdOfSizesListNewSizes);
                    }
                }
            }
            for (Colors colorsListNewColors : colorsListNew) {
                if (!colorsListOld.contains(colorsListNewColors)) {
                    Product oldProductIdOfColorsListNewColors = colorsListNewColors.getProductId();
                    colorsListNewColors.setProductId(product);
                    colorsListNewColors = em.merge(colorsListNewColors);
                    if (oldProductIdOfColorsListNewColors != null && !oldProductIdOfColorsListNewColors.equals(product)) {
                        oldProductIdOfColorsListNewColors.getColorsList().remove(colorsListNewColors);
                        oldProductIdOfColorsListNewColors = em.merge(oldProductIdOfColorsListNewColors);
                    }
                }
            }
            for (Images imagesListNewImages : imagesListNew) {
                if (!imagesListOld.contains(imagesListNewImages)) {
                    Product oldProductIdOfImagesListNewImages = imagesListNewImages.getProductId();
                    imagesListNewImages.setProductId(product);
                    imagesListNewImages = em.merge(imagesListNewImages);
                    if (oldProductIdOfImagesListNewImages != null && !oldProductIdOfImagesListNewImages.equals(product)) {
                        oldProductIdOfImagesListNewImages.getImagesList().remove(imagesListNewImages);
                        oldProductIdOfImagesListNewImages = em.merge(oldProductIdOfImagesListNewImages);
                    }
                }
            }
            for (Cart cartListNewCart : cartListNew) {
                if (!cartListOld.contains(cartListNewCart)) {
                    Product oldProductOfCartListNewCart = cartListNewCart.getProduct();
                    cartListNewCart.setProduct(product);
                    cartListNewCart = em.merge(cartListNewCart);
                    if (oldProductOfCartListNewCart != null && !oldProductOfCartListNewCart.equals(product)) {
                        oldProductOfCartListNewCart.getCartList().remove(cartListNewCart);
                        oldProductOfCartListNewCart = em.merge(oldProductOfCartListNewCart);
                    }
                }
            }
            em.getTransaction().commit();
        } catch (Exception ex) {
            String msg = ex.getLocalizedMessage();
            if (msg == null || msg.length() == 0) {
                Integer id = product.getId();
                if (findProduct(id) == null) {
                    throw new NonexistentEntityException("The product with id " + id + " no longer exists.");
                }
            }
            throw ex;
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public void destroy(Integer id) throws IllegalOrphanException, NonexistentEntityException {
        EntityManager em = null;
        try {
            em = getEntityManager();
            em.getTransaction().begin();
            Product product;
            try {
                product = em.find(Product.class, id);
                product.getId();
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The product with id " + id + " no longer exists.", enfe);
            }
            List<String> illegalOrphanMessages = null;
            List<Sizes> sizesListOrphanCheck = product.getSizesList();
            for (Sizes sizesListOrphanCheckSizes : sizesListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Product (" + product + ") cannot be destroyed since the Sizes " + sizesListOrphanCheckSizes + " in its sizesList field has a non-nullable productId field.");
            }
            List<Colors> colorsListOrphanCheck = product.getColorsList();
            for (Colors colorsListOrphanCheckColors : colorsListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Product (" + product + ") cannot be destroyed since the Colors " + colorsListOrphanCheckColors + " in its colorsList field has a non-nullable productId field.");
            }
            List<Images> imagesListOrphanCheck = product.getImagesList();
            for (Images imagesListOrphanCheckImages : imagesListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Product (" + product + ") cannot be destroyed since the Images " + imagesListOrphanCheckImages + " in its imagesList field has a non-nullable productId field.");
            }
            List<Cart> cartListOrphanCheck = product.getCartList();
            for (Cart cartListOrphanCheckCart : cartListOrphanCheck) {
                if (illegalOrphanMessages == null) {
                    illegalOrphanMessages = new ArrayList<String>();
                }
                illegalOrphanMessages.add("This Product (" + product + ") cannot be destroyed since the Cart " + cartListOrphanCheckCart + " in its cartList field has a non-nullable product field.");
            }
            if (illegalOrphanMessages != null) {
                throw new IllegalOrphanException(illegalOrphanMessages);
            }
            Category categoryId = product.getCategoryId();
            if (categoryId != null) {
                categoryId.getProductList().remove(product);
                categoryId = em.merge(categoryId);
            }
            em.remove(product);
            em.getTransaction().commit();
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

    public List<Product> findProductEntities() {
        return findProductEntities(true, -1, -1);
    }

    public List<Product> findProductEntities(int maxResults, int firstResult) {
        return findProductEntities(false, maxResults, firstResult);
    }

    private List<Product> findProductEntities(boolean all, int maxResults, int firstResult) {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            cq.select(cq.from(Product.class));
            Query q = em.createQuery(cq);
            if (!all) {
                q.setMaxResults(maxResults);
                q.setFirstResult(firstResult);
            }
            return q.getResultList();
        } finally {
            em.close();
        }
    }

    public Product findProduct(Integer id) {
        EntityManager em = getEntityManager();
        try {
            return em.find(Product.class, id);
        } finally {
            em.close();
        }
    }

    public List<Product> findProductByCategory(Integer id) {
        EntityManager em = getEntityManager();
        try {
            TypedQuery<Product> tq = em.createNamedQuery("Product.findByCategory", Product.class).setParameter("category", id);
            return tq.getResultList();
        } finally {
            em.close();
        }
    }

    public List<Product> findProductByprice(int price1,int price2) {
        EntityManager em = getEntityManager();
        try {
            TypedQuery<Product> tq = em.createNamedQuery("Product.findByPrice", Product.class).setParameter("price1", price1).setParameter("price2", price2);
            return tq.getResultList();
        } finally {
            em.close();
        }
    }

    public int getProductCount() {
        EntityManager em = getEntityManager();
        try {
            CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
            Root<Product> rt = cq.from(Product.class);
            cq.select(em.getCriteriaBuilder().count(rt));
            Query q = em.createQuery(cq);
            return ((Long) q.getSingleResult()).intValue();
        } finally {
            em.close();
        }
    }

}
